package com.payroll.framework;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Timestamp;

import javax.servlet.ServletContext;

import org.apache.log4j.Category;
import org.apache.struts.action.ActionError;

import com.payroll.framework.util.DateUtility;
import com.payroll.framework.util.PayrollErrorConstants;
import com.payroll.util.PayrollConstants;


public class Foundation {

	/**
	 * Servlet Context for application
	 */
	protected static ServletContext servletContext;


	/**
	 * Returns the default datasource as defined in the PayrollFrameworkConstants.
	 *
	 * @return A <code>Connection<code>.
	 *
	 * @throws PayrollFoundationException
	 * @throws SQLException
	 */
	public static synchronized Connection getConnection()
		throws SQLException, PayrollFoundationException {
		Connection m_connection;
		m_connection = ConnectionManager.getConnection(PayrollFrameworkConstants.DEFAULT_DATASOURCE, PayrollConstants.CONNECTION_PRIORITY_HIGH);
		m_connection.setAutoCommit(false);
		return m_connection;
	}

	/**
	 * Closes the JDBC <code>ResultSet</code>, <code>Statement</code>, and <code>Connection</code>.
	 * If the connection has not been committed, an PayrollFoundation exception will be thrown.
	 *
	 * @param p_ResultSet	The result sets to close.
	 * @param p_Statement	The statements to close.
	 * @param p_Connection	The connection to close.
	 *
	 * @throws PayrollFoundationException	thrown when a <code>SQLException</code> occurs
	 */
	public static void closeJDBCObjects(
		ResultSet[] p_resultSet,
		Statement[] p_statement,
		Connection p_connection)
		throws PayrollFoundationException {
		Category cat =
			Category.getInstance("com.payroll.framework.Foundation.closeJDBCObjects");
		// Close the result set
		try {
			for (int i = 0; i < p_resultSet.length; i++) {
				if (p_resultSet[i] != null)
					p_resultSet[i].close();
			}


			//Close the Statement
			for (int i = 0; i < p_statement.length; i++) {
				if (p_statement[i] != null)
					p_statement[i].close();
			}


			// Close the Connection
			if (p_connection != null) {
				if(!p_connection.isClosed()) {
					p_connection.close();
				}
			}


		} catch (SQLException sqe) {
			p_connection = null;
			cat.error("SQL Exception when closing connection: " + sqe.getMessage());
			sqe.printStackTrace();
			throw new PayrollFoundationException(
				"Foundation::closeJDBCObjects",
				PayrollErrorConstants.SQLException,
				sqe.getMessage());
		} finally {
			for (int i = 0; i < p_resultSet.length; i++)
				p_resultSet[i] = null;
			for (int i = 0; i < p_statement.length; i++)
				p_statement[i] = null;
			try {
				if (p_connection != null)
					if (!p_connection.isClosed())
						p_connection.close();
			} catch (SQLException e) {
				cat.error("SQL Exception when closing connection: " + e.getMessage());
				e.printStackTrace();
				throw new PayrollFoundationException(
					"Foundation::closeJDBCObjects",
					PayrollErrorConstants.SQLException,
					e.getMessage());
			}
			p_connection = null;
		}


	}


	/**
	 * Closes the JDBC <code>Statement</code> and <code>Connection</code>.
	 * If the connection has not been committed, an PayrollFoundation exception will be thrown.
	 *
	 * @param p_Statement	The statements to close.
	 * @param p_Connection	The connection to close.
	 *
	 * @throws PayrollFoundationException	thrown when a <code>SQLException</code> occurs
	 */
	public static void closeJDBCObjects(
		Statement[] p_statement,
		Connection p_connection)
		throws PayrollFoundationException {
		Category cat =
			Category.getInstance("com.payroll.framework.Foundation.closeJDBCObjects");


		try {
			//Close the Statement
			for (int i = 0; i < p_statement.length; i++) {
				if (p_statement[i] != null)
					p_statement[i].close();
			}


			// Close the Connection
			if(p_connection != null) {
				if(!p_connection.isClosed()) {
					p_connection.close();
				}
			}

		} catch (SQLException sqe) {
			if(p_connection != null)
				p_connection = null;
			cat.error("SQL Exception when closing connection: " + sqe.getMessage());
			sqe.printStackTrace();
			throw new PayrollFoundationException(
				"Foundation::closeJDBCObjects",
				PayrollErrorConstants.SQLException,
				sqe.getMessage());
		} finally {
			for (int i = 0; i < p_statement.length; i++)
				p_statement[i] = null;
			try {
				if (p_connection != null)
					if (!p_connection.isClosed())
						p_connection.close();
			} catch (SQLException e) {
				cat.error("SQL Exception when closing connection: " + e.getMessage());
				e.printStackTrace();
				throw new PayrollFoundationException(
					"Foundation::closeJDBCObjects",
					PayrollErrorConstants.SQLException,
					e.getMessage());
			}
			p_connection = null;
		}


	}

	/**
	 * Rollbacks the database transactions. An PayrollFoundation exception will be thrown on error.
	 *
	 * @param p_Connection	The connection to rollback.
	 *
	 * @throws PayrollFoundationException	thrown when a <code>SQLException</code> occurs.
	 */
	public static void rollback(Connection p_connection)
		throws PayrollFoundationException {
		Category cat = Category.getInstance("com.payroll.framework.Foundation.rollback");


		try {
			if(p_connection != null)
				p_connection.rollback();
		} catch (SQLException e) {
			cat.fatal("SQL Exception thrown during rollback.  Error: " + e.getMessage());
			throw new PayrollFoundationException(
				"Foundation::rollback",
				PayrollErrorConstants.SQLException,
				e.getMessage());
		}
	}


	/**
	 * Commits the database transactions. An PayrollFoundation exception will be thrown on error.
	 *
	 * @param p_Connection	The connection to commit.
	 *
	 * @throws PayrollFoundationException	thrown when a <code>SQLException</code> occurs.
	 */
	public static void commit(Connection p_connection)
		throws PayrollFoundationException {
		Category cat = Category.getInstance("com.payroll.framework.Foundation.commit");


		try {
			if(p_connection != null)
				p_connection.commit();
		} catch (SQLException e) {
			cat.fatal("SQL Exception thrown during commit.  Error: " + e.getMessage());
			throw new PayrollFoundationException(
				"Foundation::commit",
				PayrollErrorConstants.SQLException,
				e.getMessage());
		}
	}

	/**
	 * Closes the JDBC <code>ResultSet</code>, <code>Statement</code>, and <code>Connection</code>.
	 * If the connection has not been committed, an PayrollFoundation exception will be thrown.
	 *
	 * @param p_resultSet	The <code>ResultSet</code> to close.
	 * @param p_Statement	The <code>Statement</code> to close.
	 * @param p_Connection	The <code>Connection</code> to close.
	 *
	 * @throws PayrollFoundationException	thrown when a <code>SQLException</code> occurs
	 */
	public static void closeJDBCObjects(
		ResultSet p_resultSet,
		Statement p_statement,
		Connection p_connection)
		throws PayrollFoundationException {
		Category cat =
			Category.getInstance("com.payroll.framework.Foundation.closeJDBCObjects");
		try {
			if (p_resultSet != null)
				p_resultSet.close();


			if (p_statement != null)
				p_statement.close();


			if (p_connection != null) {
				if(!p_connection.isClosed()) {
					p_connection.close();
				}
			}
		} catch (SQLException sqe) {
			cat.error("SQL Exception when closing connection: " + sqe.getMessage());
			sqe.printStackTrace();
			throw new PayrollFoundationException(
				"Foundation::closeJDBCObjects",
				PayrollErrorConstants.SQLException,
				sqe.getMessage());
		} finally {
			p_resultSet = null;
			p_statement = null;
			try {
				if (p_connection != null)
					if (!p_connection.isClosed())
						p_connection.close();
			} catch (SQLException e) {
				cat.error("SQL Exception when closing connection: " + e.getMessage());
				e.printStackTrace();
				throw new PayrollFoundationException(
					"Foundation::closeJDBCObjects",
					PayrollErrorConstants.SQLException,
					e.getMessage());
			}
			p_connection = null;
		}
	}


	/**
	 * Closes the JDBC <code>Statement</code> and <code>Connection</code>.
	 * If the connection has not been committed, an PayrollFoundation exception will be thrown.
	 *
	 * @param p_Statement	The <code>Statement</code> to close.
	 * @param p_Connection	The <code>Connection</code> to close.
	 *
	 * @throws PayrollFoundationException	thrown when a <code>SQLException</code> occurs
	 */
	public static void closeJDBCObjects(
		Statement p_statement,
		Connection p_connection)
		throws PayrollFoundationException {
		Category cat =
			Category.getInstance("com.payroll.framework.Foundation.closeJDBCObjects");
		try {
			if (p_statement != null)
				p_statement.close();


			if (p_connection != null) {
				if(!p_connection.isClosed()) {
					p_connection.close();
				}
			}
		} catch (SQLException sqe) {
			cat.error("SQL Exception when closing connection: " + sqe.getMessage());
			sqe.printStackTrace();
			throw new PayrollFoundationException(
				"Foundation::closeJDBCObjects",
				PayrollErrorConstants.SQLException,
				sqe.getMessage());
		} finally {
			p_statement = null;
			try {
				if (p_connection != null)
					if (!p_connection.isClosed())
						p_connection.close();
			} catch (SQLException e) {
				cat.error("SQL Exception when closing connection: " + e.getMessage());
				e.printStackTrace();
				throw new PayrollFoundationException(
					"Foundation::closeJDBCObjects",
					PayrollErrorConstants.SQLException,
					e.getMessage());
			}
			p_connection = null;
		}
	}
	/**
	 * Gets the current <code>Timestamp</code>
	 *
	 * @return the current <code>Timestamp</code>
	 */
	public static Timestamp getCurrentTimestamp() {
		return DateUtility.getCurrentTimestamp();
	}

	/**
	 * Returns the specified property from the global properties hashtable.
	 *
	 * @param p_Key The property key.
	 *
	 * @return The requested property value.
	 */
	public static String getProperty(String p_Key) {
		String m_property;
		m_property = System.getProperty(p_Key);


		if ( m_property == null) {
			return PayrollFrameworkProperties.getProperty(p_Key);
		} else {
			return m_property;
		}
	}
	/**
	 * Gets the <code>ServletContext</code>
	 *
	 * @return the <code>ServletContext</code>
	 */
	public static javax.servlet.ServletContext getServletContext() {
		return servletContext;
	}
	/**
	 * Get a formatted error message
	 *
	 * @param p_ActionError the <code>ActionError</code> that has additional
	 * 						parameters to insert into the error message
	 *
	 * @return A formatted error message
	 *
	 */
	public static String getFormattedEXCMessage(ActionError p_ActionError) {
		return (
			(PayrollErrorManager) PayrollErrorManager.getInstance()).getFormattedErrorMessage(
			p_ActionError);
	}
	/**
	 * Sets the Tran Stats manager on or off (true/false)
	 *
	 * @param p_TranStatsOn true turns the tran stats manager on. false turns the tran stats manager off.
	 */
	public static void setTranStats(boolean p_TranStatsOn) {
		if (p_TranStatsOn)
			TranStatsManager.setTranStatsOn();
		else
			TranStatsManager.setTranStatsOff();
	}
	/**
	 * Sets the i_ServletContext
	 *
	 * @param newI_ServletContext the <code>ServletContext<code>
	 */
	public static void setServletContext( ServletContext p_servletContext) {
		servletContext = p_servletContext;
	}
	/**
	 * Initalizes the application security, reference data cache, log4j,
	 * and jabber based upon values from properties files.
	 *
	 * @throws AMSFoundationException	thrown when an <code>Exception</code>
	 * 									occurs when initialize the reference
	 * 									data cache.
	 */
	public static void initialize() throws PayrollFoundationException {

		Category cat = Category.getInstance("Foundation.initialize");

		// Load Error manager
		PayrollErrorManager err = new PayrollErrorManager();
		err.loadCache();

		//String m_securityProviderName = "";


			//END JEY IR-8564
		//if (System.getProperty("log4jDebugLevel") != null)
			//cat.getRoot().setPriority(Priority.toPriority(System.getProperty("log4jDebugLevel")));



	}


}
